//-------------------------------------------------------------------------
// File: Color.cpp
//
// Descr.: - todo -
//
// Author: Stefan Leihkauf
// Date:   02.03.2014
//-------------------------------------------------------------------------
#include "cb_pch.h"
#include "Color.h"

namespace cb { namespace gfx {

//-------------------------------------------------------------------------
const unsigned mask_r_8888 = 0xFF000000;
const unsigned mask_g_8888 = 0x00FF0000;
const unsigned mask_b_8888 = 0x0000FF00;
const unsigned mask_a_8888 = 0x000000FF;

//-------------------------------------------------------------------------
// clamp values to [0.0 ; 1.0]
//-------------------------------------------------------------------------
#define clamp(a) (((a) < 0.f) ? 0.f : ((a) > 1.f) ? 1.f : (a))

//-------------------------------------------------------------------------
/**
*/
Color::Color()
{
	_color[iR] = 0.f;
	_color[iG] = 0.f;
	_color[iB] = 0.f;
	_color[iA] = 0.f;
}

//-------------------------------------------------------------------------
/**
*/
Color::Color(const Color& other)
{
	_color[iR] = other._color[iR];
	_color[iG] = other._color[iG];
	_color[iB] = other._color[iB];
	_color[iA] = other._color[iA];
}

//-------------------------------------------------------------------------
/**
*/
Color::Color(float r, float g, float b, float a /*= 1.0f*/)
{
	_color[iR] = clamp(r);
	_color[iG] = clamp(g);
	_color[iB] = clamp(b);
	_color[iA] = clamp(a);
}

//-------------------------------------------------------------------------
/**
*/
void Color::Set(float r, float g, float b, float a)
{
	_color[iR] = clamp(r);
	_color[iG] = clamp(g);
	_color[iB] = clamp(b);
	_color[iA] = clamp(a);
}

//-------------------------------------------------------------------------
/**
*/
/*static*/ float Color::Clamp(float f)
{
    return clamp(f);
}

//-------------------------------------------------------------------------
/**
*/
bool Color::operator == (const Color& other) const
{
	return (
		(_color[iR] == other._color[iR]) && 
		(_color[iG] == other._color[iG]) && 
		(_color[iB] == other._color[iB]) && 
		(_color[iA] == other._color[iA]));
}

//-------------------------------------------------------------------------
/**
*/
Color& Color::operator = (const Color& other)
{
	_color[iR] = other._color[iR];
	_color[iG] = other._color[iG];
	_color[iB] = other._color[iB];
	_color[iA] = other._color[iA];

	return *this;
}

//-------------------------------------------------------------------------
/**
*/
float& Color::operator [] (int index)
{
	assert((index >= 0) && (index < 4));

	return _color[index];
}

//-------------------------------------------------------------------------
/**
*/
float Color::operator [] (int index) const
{
	if((index >= 0) && (index < 4))
		return _color[index];

	return 0.0f;
}

//-------------------------------------------------------------------------
/**
*/
ushort Color::toRGB565() const
{
	ushort r = (ushort)(clamp(_color[iR]) * 31.f);
	ushort g = (ushort)(clamp(_color[iG]) * 63.f);
	ushort b = (ushort)(clamp(_color[iB]) * 31.f);

	return ((r << 11) | (g << 5) | b);
}

//-------------------------------------------------------------------------
/**
*/
unsigned Color::toRGBA8888() const
{
	ushort r = (ushort)(clamp(_color[iR]) * 255.f);
	ushort g = (ushort)(clamp(_color[iG]) * 255.f);
	ushort b = (ushort)(clamp(_color[iB]) * 255.f);
	ushort a = (ushort)(clamp(_color[iA]) * 255.f);

	return ((r << 24) | (g << 16) | (b << 8) | a);
}

//-------------------------------------------------------------------------
/**
*/
/*static*/ Color Color::fromRGB565(ushort color)
{
	float r = clamp(((float)((color & 0xF800) >> 11) / 31.f));
	float g = clamp(((float)((color & 0x07E0) >> 5) / 63.f));
	float b = clamp(((float)((color & 0x001F) >> 0) / 31.f));

	return Color(r, g, b, 1.0f);
}

//-------------------------------------------------------------------------
/**
*/
/*static*/ Color Color::fromRGBA8888(unsigned color)
{
	float r = clamp(((float)((color & mask_r_8888) >> 24) / 255.f));
	float g = clamp(((float)((color & mask_g_8888) >> 16) / 255.f));
	float b = clamp(((float)((color & mask_b_8888) >> 8) / 255.f));
	float a = clamp(((float)((color & mask_a_8888) >> 0) / 255.f));

	return Color(r, g, b, a);
}

}} // cb::gfx